/* This file is part of the Crimsoon project
  * Copyright (C) 2009 Eduardo Henrique <eduardohleite@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public License
  * along with this library; see the file COPYING.LIB.  If not, write to
  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
*/

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QIcon>
#include <QLabel>
#include <QTime>
#include <QMessageBox>
#include <QTextStream>
#include <QFile>

#include "playpanel.h"
#include "playlist.h"
#include "gallery.h"
#include "track.h"

void PlayPanel::createWidgets()
{
    QIcon icon;

    mainLayout = new QVBoxLayout;
    sliderLayout = new QHBoxLayout;

    slider = new Phonon::SeekSlider;
    slider->setMediaObject(mediaObject);
    sliderLayout->addWidget(slider);
    time = new QLabel("00:00");
    sliderLayout->addSpacing(10);
    sliderLayout->addWidget(time);

    mainLayout->addLayout(sliderLayout);

    buttonsLayout = new QHBoxLayout;

    playPauseButton = new QPushButton;
    previousButton = new QPushButton;
    stopButton = new QPushButton;
    nextButton = new QPushButton;

    connect(playPauseButton, SIGNAL(clicked()), this, SLOT(onPlayPauseClicked()));
    connect(previousButton, SIGNAL(clicked()), this, SLOT(onPreviousClicked()));
    connect(stopButton, SIGNAL(clicked()), this, SLOT(onStopClicked()));
    connect(nextButton, SIGNAL(clicked()), this, SLOT(onNextClicked()));

    icon = QIcon::QIcon(":img/previous.png");
    previousButton->setIcon(icon);
    previousButton->setFixedSize(40,40);

    icon = QIcon::QIcon(":img/play.png");
    playPauseButton->setIcon(icon);
    playPauseButton->setFixedSize(40,40);

    icon = QIcon::QIcon(":img/stop.png");
    stopButton->setIcon(icon);
    stopButton->setFixedSize(40,40);

    icon = QIcon::QIcon(":img/next.png");
    nextButton->setIcon(icon);
    nextButton->setFixedSize(40,40);

    disableControls();

    volume = new Phonon::VolumeSlider(this);
    volume->setAudioOutput(audioOutput);
    volume->setFixedWidth(150);

    buttonsLayout->addWidget(previousButton);
    buttonsLayout->addWidget(playPauseButton);
    buttonsLayout->addWidget(stopButton);
    buttonsLayout->addWidget(nextButton);
    buttonsLayout->addStretch();
    buttonsLayout->addWidget(volume);
    mainLayout->addLayout(buttonsLayout);

    this->setLayout(mainLayout);
}

void PlayPanel::forceStop()
{
    if (mediaObject->state() == Phonon::PlayingState)
    {
        mediaObject->stop();
    }
}

void PlayPanel::prepare(QString filename)
{
    Phonon::MediaSource source(filename);

    if (mediaObject->state() == Phonon::PlayingState)
    {
        mediaObject->stop();
    }

    resetPlaylist();
    playlist->append(source);
    disableControls();
    mediaObject->setCurrentSource(source);
}

void PlayPanel::prepare(PlayList *files, qint32 startIndex, bool autoPlay)
{
    if (mediaObject->state() == Phonon::PlayingState)
    {
        mediaObject->stop();
    }

    resetPlaylist();
    foreach (Track track, *files)
    {
        Phonon::MediaSource source(track.getFileName());
        playlist->append(source);
    }

    if (!playlist->isEmpty())
    {
        disableControls();        
        mediaObject->setCurrentSource(playlist->at(startIndex));

        if (autoPlay)
        {
            mediaObject->play();
        }
    }
}

void PlayPanel::disableControls()
{
    previousButton->setEnabled(false);
    playPauseButton->setEnabled(false);
    stopButton->setEnabled(false);
    nextButton->setEnabled(false);
}

void PlayPanel::resetPlaylist()
{
    playlist = new QList<Phonon::MediaSource>;
}

QString PlayPanel::currentFile()
{
    qint32 index = playlist->indexOf(mediaObject->currentSource());
    return playlist->at(index).fileName();
}

void PlayPanel::onPlayPauseClicked()
{
    if (mediaObject->state() == Phonon::PlayingState)
    {
        mediaObject->pause();
    }
    else
    {
        mediaObject->play();
    }

    autoPlay = false;
}

void PlayPanel::onStopClicked()
{
    mediaObject->stop();
    autoPlay = false;
}

void PlayPanel::onPreviousClicked()
{
    if (mediaObject->state() == Phonon::PlayingState)
    {
        mediaObject->stop();
    }

    qint32 index = playlist->indexOf(mediaObject->currentSource()) - 1;
    autoPlay = true;
    mediaObject->setCurrentSource(playlist->at(index));
}

void PlayPanel::onNextClicked()
{
    if (mediaObject->state() == Phonon::PlayingState)
    {
        mediaObject->stop();
    }

    qint32 index = playlist->indexOf(mediaObject->currentSource()) + 1;
    autoPlay = true;
    mediaObject->setCurrentSource(playlist->at(index));
}

void PlayPanel::onMediaStateChanged(Phonon::State state, Phonon::State)
{
    if (state == Phonon::StoppedState)
    {           
        playPauseButton->setEnabled(true);
        QIcon icon(":img/play.png");
        playPauseButton->setIcon(icon);

        stopButton->setEnabled(false);

        status = PLAYPANEL_STOPPED;

        if (autoPlay)
        {
            mediaObject->play();
            autoPlay = false;
        }
    }
    else if (state == Phonon::PlayingState)
    {
        playPauseButton->setEnabled(true);
        stopButton->setEnabled(true);
        QIcon icon(":img/pause.png");
        playPauseButton->setIcon(icon);

        status = PLAYPANEL_PLAYING;
    }
    else if (state == Phonon::PausedState)
    {
        playPauseButton->setEnabled(true);
        stopButton->setEnabled(true);
        QIcon icon(":img/play.png");
        playPauseButton->setIcon(icon);

        status = PLAYPANEL_PAUSED;
    }
    else if (state == Phonon::ErrorState)
    {
        status = PLAYPANEL_ERROR;

        QString message;
        QTextStream (&message) << "Could not play file ";

        QMessageBox::warning(this, tr("Error playing file"),
                             message, QMessageBox::Ok);
    }

    emit statusChanged();
}

void PlayPanel::onMediaSourceChanged(const Phonon::MediaSource &source)
{
    previousButton->setEnabled((playlist->indexOf(mediaObject->currentSource()) > 0));
    nextButton->setEnabled(playlist->indexOf(mediaObject->currentSource()) < playlist->size() - 1);

    time->setText("00:00");

    emit playFileChanged(source.fileName());
}

void PlayPanel::onPlaybackFinished()
{

}

void PlayPanel::onPlaybackAboutToFinish()
{
    if (mode == PLAYPANEL_REPEAT)
    {
        mediaObject->enqueue(mediaObject->currentSource());
    }
    else
    {
        qint32 index = playlist->indexOf(mediaObject->currentSource()) + 1;
        if (playlist->size() > index)
        {
            QFile file;
            Gallery gallery;
            while (!file.exists(playlist->at(index).fileName()))
            {
                QString message;
                QTextStream (&message) << "Could not find file " << playlist->at(index).fileName()
                        << ".\n Remove it from gallery?";

                if (QMessageBox::question(this, tr("Error"), message, QMessageBox::Yes, QMessageBox::No)
                        == QMessageBox::Yes)
                {
                    gallery.removeAudioFile(playlist->at(index).fileName());
                    emit playFileNotFound(playlist->at(index).fileName());
                }

                index++;
            }

            mediaObject->enqueue(playlist->at(index));
        }
        else
        {
            if (mode == PLAYPANEL_REPEAT_ALL)
            {
                mediaObject->enqueue(playlist->at(0));
            }
        }
    }
}

void PlayPanel::onTick(qint64 timestamp)
{
    QTime displayTime(0, (timestamp / 60000) % 60, (timestamp / 1000) % 60);
    time->setText(displayTime.toString("mm:ss"));
}

PlayPanel::PlayPanel()
{
    setFixedHeight(80);

    mediaObject = new Phonon::MediaObject(this);
    audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);

    mediaObject->setTickInterval(1000);

    connect(mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
            this, SLOT(onMediaStateChanged(Phonon::State,Phonon::State)));
    connect(mediaObject, SIGNAL(finished()), this, SLOT(onPlaybackFinished()));
    connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(onPlaybackAboutToFinish()));
    connect(mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),
            this, SLOT(onMediaSourceChanged(Phonon::MediaSource)));
    connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(onTick(qint64)));

    Phonon::createPath(mediaObject, audioOutput);

    playlist = new QList<Phonon::MediaSource>;

    createWidgets();

    autoPlay = false;
    status = PLAYPANEL_READY;
}

PlayPanel::~PlayPanel()
{
    delete sliderLayout;
    delete mainLayout;
    delete buttonsLayout;
    delete slider;
    delete volume;
    delete playPauseButton;
    delete stopButton;
    delete previousButton;
    delete nextButton;
    delete time;

    delete mediaObject;
    delete audioOutput;

    delete playlist;
}
